home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
simula
/
books
/
books.lha
/
kirkerud
/
studchain.sim
< prev
next >
Wrap
Text File
|
1993-08-16
|
18KB
|
439 lines
% ****************************************************************
% * *
% * This is the program constructed in section 14.3 of *
% * Object Oriented Programming with Simula by Bj|rn Kirkerud; *
% * *
% ****************************************************************
begin
% ****************************************************************
% * *
% * Declarations of auxiliary procedures: *
% * *
% ****************************************************************
character procedure prompt_for_char(prompt); text prompt;
begin
outtext(prompt); breakoutimage; inimage;
prompt_for_char := inchar;
end of prompt_for_char;
integer procedure prompt_for_int(prompt); text prompt;
begin
outtext(prompt); breakoutimage; inimage;
prompt_for_int := inint;
end of prompt_for_int;
real procedure prompt_for_real(prompt); text prompt;
begin
outtext(prompt); breakoutimage; inimage;
prompt_for_real := inreal;
end of prompt_for_real;
Boolean procedure prompt_for_bool(prompt); text prompt;
begin character c;
outtext(prompt); breakoutimage; inimage;
c := inchar;
prompt_for_bool := c = 'y' or c = 'Y';
end of prompt_for_bool;
procedure User_message(message); text message;
begin outtext(message); outimage end;
text procedure int_as_text(int); integer int;
begin text t;
t :- blanks(size_of_int(int));
t.putint(int);
int_as_text :- t;
end;
integer procedure size_of_int(int); integer int;
begin integer a;
a := abs(int);
size_of_int := (if int < 0 then 1 else 0) +
(if a < 10 then 1 else
if a < 100 then 2 else
if a < 1000 then 3 else
if a < 10000 then 4 else
if a < 100000 then 5 else
if a < 1000000 then 6 else
if a < 10000000 then 7 else
if a < 100000000 then 8 else
if a < 1000000000 then 9 else 10);
end;
% ****************************************************************
% * *
% * The class Student: *
% * *
% ****************************************************************
class Student;
begin
integer ident, year, month, day, form;
Boolean female;
character math_grade, eng_grade, hist_grade;
text procedure key; key :- int_as_text(ident);
! A variable to hold a reference to the next Student in a pointer chain: ;
ref(Student) next_in_chain;
procedure read;
begin
ident := prompt_for_int("Identity number? ");
year := prompt_for_int("Year of birth? ");
month := prompt_for_int("Month? ");
day := prompt_for_int("Day? ");
form := prompt_for_int("Form? ");
female := prompt_for_bool("Female? ");
math_grade := prompt_for_char("Grade in mathematics? ");
eng_grade := prompt_for_char("Grade in English? ");
hist_grade := prompt_for_char("Grade in history? ");
end of Student'read;
procedure write;
begin
outtext("Data for student: "); outint(ident, 6);
outtext(". Born: "); outint(day, 2); outchar('/');
outint(month, 2); outchar('/');
outint(year, 4);
outtext(if female then ". Female." else ". Male."); outimage;
outtext(" Form: "); outint(form, 1);
outtext(". Current grades:");
outtext(" Mathematics: "); outchar(math_grade);
outtext(" English: "); outchar(eng_grade);
outtext(" History: "); outchar(hist_grade); outimage;
end of Student'write;
procedure change;
begin character attribute;
attribute := prompt_for_char("What do you want to change? ");
if attribute = 'i' then ident
:= prompt_for_int("New identity number? ") else
if attribute = 'y' then year
:= prompt_for_int("New birth year? ") else
if attribute = 'm' then month
:= prompt_for_int("New birth month? ") else
if attribute = 'd' then day
:= prompt_for_int("New day of birth? ") else
if attribute = 'f' then form
:= prompt_for_int("New form number? ") else
if attribute = 's' then female
:= prompt_for_bool("Female? ") else
if attribute = 'a' then math_grade
:= prompt_for_char("New grade in math? ") else
if attribute = 'e' then eng_grade
:= prompt_for_char("New grade in English? ") else
if attribute = 'h' then hist_grade
:= prompt_for_char("New grade in history? ")
else begin
User_message("You can change one of the following attributes:");
User_message(" i: Identity number");
User_message(" y: Birth year");
User_message(" m: Birth month");
User_message(" d: Day of birth");
User_message(" f: Form number");
User_message(" s: Sex");
User_message(" a: Grade in mathematics");
User_message(" e: Grade in English");
User_message(" h: Grade in history");
change; ! Observe that this is an invocation of the procedure
! being declared. The effect is that user is given
! another chance to change;
end;
end of Student'change;
character procedure worst_grade;
worst_grade := max(math_grade, max(eng_grade, hist_grade));
procedure put_in_record(outf); ref(outfile) outf;
inspect outf do
begin
outint(ident, 6);
outint(year, 5); outint(month, 3); outint(day, 3);
outint(form, 2); outint(if female then 1 else 0, 2);
outchar(math_grade); outchar(eng_grade); outchar(hist_grade);
end;
procedure get_from_record(inf); ref(infile) inf;
inspect inf do
begin
ident := inint;
year := inint; month := inint; day := inint;
form := inint; female := inint = 1;
math_grade := inchar; eng_grade := inchar; hist_grade := inchar;
end;
end of Student;
% ****************************************************************
% * *
% * The class School: *
% * *
% ****************************************************************
class School;
protected first_in_chain, last_in_traversal;
begin
! Declaration of a variable to hold a reference to the first Student
! in the pointer chain: ;
ref(Student) first_in_chain;
! Declaration of a variable to hold a reference to the Student
! last vistited in a traversal of the chain: ;
ref(Student) last_in_traversal;
! Declarations of data access procedures: ;
procedure Place_student(a_student, student_exists);
name student_exists; ref(Student) a_student; Boolean student_exists;
begin
student_exists := false;
if first_in_chain == none
then first_in_chain :- a_student
! The new object is placed first;
else if a_student.key < first_in_chain.key
then begin
a_student.next_in_chain :- first_in_chain;
first_in_chain :- a_student;
! The new object is placed first;
end
else begin ref(Student) aux_stud; Boolean aux_found;
aux_stud :- first_in_chain; aux_found := false;
while not aux_found do
if aux_stud.next_in_chain == none then aux_found := true
else if a_student.key < aux_stud.next_in_chain.key
then aux_found := true
else aux_stud :- aux_stud.next_in_chain;
if a_student.key = aux_stud.key
then student_exists := true
else begin
a_student.next_in_chain :- aux_stud.next_in_chain;
aux_stud.next_in_chain :- a_student;
! The new object is placed after aux_stud;
end;
end;
end of Place_student;
ref(Student) procedure find_student(key); text key;
! This version assumes that the pointer chain is sorted
! on increasing key-values;
begin ref(Student) aux_stud; Boolean found;
aux_stud :- first_in_chain;
while aux_stud =/= none and not found do
if aux_stud.key > key then aux_stud :- none else
if aux_stud.key = key then found := true
else aux_stud :- aux_stud.next_in_chain;
find_student :- aux_stud;
end of find_student;
ref(Student) procedure first_student;
begin
first_student :- first_in_chain;
last_in_traversal :- first_in_chain;
end;
ref(Student) procedure next_student;
if last_in_traversal == none then next_student :- none
else begin
last_in_traversal :- last_in_traversal.next_in_chain;
next_student :- last_in_traversal;
end;
procedure Remove_specified_student(key, no_such_student);
name no_such_student; text key; Boolean no_such_student;
begin ref(Student) aux_stud, pred_stud; Boolean found;
aux_stud :- first_in_chain;
while aux_stud =/= none and not found do
if aux_stud.key = key then found := true
else begin
pred_stud :- aux_stud;
aux_stud :- aux_stud.next_in_chain;
end;
if aux_stud == none then no_such_student := true
else begin
no_such_student := false;
if pred_stud == none
then first_in_chain :- first_in_chain.next_in_chain
else pred_stud.next_in_chain :- aux_stud.next_in_chain;
end;
end of Remove_student;
end of School;
% ****************************************************************
% * *
% * Start of School-context: *
% * *
% ****************************************************************
School begin
% ****************************************************************
% * *
% * Declarations of command procedures: *
% * *
% ****************************************************************
procedure Give_help;
begin
User_message("The legal commands are: ");
User_message(" ?: Help (writes this text)");
User_message(" N: To enter data about a new student");
User_message(" W: Writes data about a specified student");
User_message(" L: Writes a list with all students");
User_message(" C: Changes data about a specified student");
User_message(" R: Removes all data about a specified student");
User_message(" P: Puts all data to file ""stud.dta""");
User_message(" G: Gets data from file ""stud.dta""");
User_message(" B: Writes students with bad grades");
User_message(" Q: Quit (the program execution stops)");
end of Give_help;
procedure Enter_student;
begin ref(Student) a_student; Boolean ident_exists;
a_student :- new Student;
a_student.read;
Place_student(a_student, ident_exists);
if ident_exists
then User_message("The identity number is already in use!")
else User_message("The data have been stored.");
end of Enter_student;
procedure Write_student;
begin integer ident_number; ref(Student) a_student;
ident_number := prompt_for_int("Identity number? ");
a_student :- find_student(int_as_text(ident_number));
if a_student == none
then User_message("No student with that identity number!")
else a_student.write;
end of Write_student;
procedure List_students;
begin ref(Student) a_student;
User_message("The students for which data have been entered:");
a_student :- first_student;
while a_student =/= none do
begin a_student.write; a_student :- next_student end;
end of List_students;
procedure Change_student;
begin ref(Student) a_student; integer ident_number;
ident_number := prompt_for_int("Identity number? ");
a_student :- find_student(int_as_text(ident_number));
if a_student == none
then User_message("No student with that identity number!")
else begin a_student.write; a_student.change end;
end of Change_student;
procedure Remove_student;
begin integer ident_number; Boolean no_such_student;
ident_number := prompt_for_int("Identity number? ");
Remove_specified_student(int_as_text(ident_number), no_such_student);
if no_such_student
then User_message("No student with that identity number!")
else User_message("The student has been removed!");
end of Remove_student;
procedure Put_to_file;
begin ref(Student) a_student;
inspect new outfile("stud.dta") do
begin
open(blanks(24));
a_student :- first_student;
while a_student =/= none do
begin
a_student.put_in_record(this outfile);
outimage;
a_student :- next_student;
end;
close;
end;
end of Put_to_file;
procedure Get_from_file;
begin ref(Student) a_student; Boolean ident_exists;
inspect new infile("stud.dta") do
begin
open(blanks(24)); inimage;
while not endfile do
begin
a_student :- new Student;
a_student.get_from_record(this infile);
Place_student(a_student, ident_exists);
inimage;
end;
close;
end;
end of Get_from_file;
procedure Bad_grades;
begin character grade_limit; ref(Student) a_student;
grade_limit := prompt_for_char("Grade limit? ");
a_student :- first_student;
while a_student =/= none do
begin
if a_student.worst_grade ge grade_limit then a_student.write;
a_student :- next_student;
end;
end of Bad_grades;
procedure Unknown_command(c); character c;
begin
outtext(" You gave the command '"); outchar(c);
outtext("'. This is not among the legal commands."); outimage;
outtext(" Type ? if you don't remember the legal commands");
outimage;
end of Unknown command;
% ****************************************************************
% * *
% * Declaration of a variable to keep the latest command *
% * typed by the user: *
% * *
% ****************************************************************
character command;
% ****************************************************************
% * *
% * That was the last declaration. *
% * Now come the imperatives of the program: *
% * *
% ****************************************************************
command := prompt_for_char("Type your first command (? for help) > ");
while command ne 'Q' do
begin
if command = '?' then Give_help else
if command = 'N' then Enter_student else
if command = 'W' then Write_student else
if command = 'L' then List_students else
if command = 'C' then Change_student else
if command = 'R' then Remove_student else
if command = 'P' then Put_to_file else
if command = 'G' then Get_from_file else
if command = 'B' then Bad_grades
else Unknown_command(command);
command := prompt_for_char("Your next command > ");
end;
User_message("Bye");
end of block prefixed by School;
end